package org.budo.dubbo.protocol.http.aop.permission.user;

import java.io.Serializable;
import java.lang.reflect.Method;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.budo.dubbo.protocol.http.authentication.AuthenticationCheckService;
import org.budo.dubbo.protocol.http.authentication.AuthenticationCheckService.Fail;
import org.springframework.core.annotation.Order;

import lombok.Setter;
import lombok.extern.slf4j.Slf4j;

/**
 * @author lmw
 */
@Slf4j
@Setter
@Order(1010)
public class UserPermissionCheckMethodInterceptor extends AbstractUserPermissionCheckInterceptor implements MethodInterceptor {
    /**
     * @see UserPermissionCheckHandlerInterceptor#preHandle(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse,Object)
     */
    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
        Method method = invocation.getMethod();
        Boolean requireUserPermissionCheck = UserPermissionCheckUtil.requireUserPermissionCheck(method);

        // 当前请求不需要验证
        if (!requireUserPermissionCheck) {
            return invocation.proceed();
        }

        AuthenticationCheckService _authenticationCheckService = this.getAuthenticationCheckService();
        if (null == _authenticationCheckService) {
            log.error("#38 _authenticationCheckService is null, invocation=" + invocation);
            return invocation.proceed();
        }

        Serializable _authenticationPrincipal = _authenticationCheckService.getAuthenticationPrincipal();
        if ((null == _authenticationPrincipal || _authenticationPrincipal instanceof Fail)) {
            this.handleAuthFailed(invocation.getMethod(), _authenticationPrincipal);
            return null;
        }

        String permissionName = this.permissionName(method);
        Boolean hasPermission = this.hasPermission(_authenticationPrincipal, permissionName);
        if (hasPermission) {
            return invocation.proceed(); // 权限检查通过
        }

        this.handlePermissionFailed(_authenticationPrincipal, permissionName);
        return null;
    }
}
